using System;
using System.Collections.Generic;
using System.Reflection;
using QntPlatform.Strategy.CmdCtrl;
using System.Linq;
namespace QntPlatform.Strategy.S2
{
    /* <summary>激进-突破信号：突破买入以持仓亏损的10% （20x杠杆）行情下跌0.5%止损，以为持仓盈利的30%进行平仓1/2，剩余追踪止盈
    20x杠杆
    止损为：购入价格*（1-0.5%）
    止盈为：（当前价格/购入价格)>0.015时平一半，剩余追踪
    思路：收到多空信号
    计算：止损、止盈
 </summary>
*/
    [ArgInfo(Remark = @"激进-突破信号(普通突破);
    计算执行：仓位、止损，1/2止盈、保本止损、1/2追踪止盈
    请求内容格式：{""Period"":60,""islong"":true}
    止损为：购入价格*（1-0.5%）
     止盈为：（当前价格/购入价格)>0.015时平一半，剩余追踪
")]
    public class TuPo_2 : PeriodTrandBase<TuPo_2.TradeCmd>
    {
        /// 仓位最大可承受亏损
        [ArgInfo(Remark = "仓位最大可承受亏损")]
        decimal accountMaxLossRatio { get; set; } = 0.02m;
        /// 止损计算亏损率
        [ArgInfo(Remark = "止损计算亏损率")]
        decimal stopLossRatio { get; set; } = 0.005m;
        /// 第一止盈点止盈率
        [ArgInfo(Remark = "第一止盈点止盈率")]
        public decimal ProfitRate1 { get; set; } = 0.015m;



        /// <summary>
        /// 追踪止盈回撤率=1-当前盈利率/最高盈利率
        /// </summary>
        [ArgInfo(Remark = "追踪止盈回撤率=1-当前盈利率/最高盈利率",DefaultVal ="0.001")]
        public decimal profitSlideRate { get; set; }=0.001m;
        /// <summary>
        ///  跟踪止盈的最小盈利率，大于这个盈利率才会止盈
        /// </summary>
        [ArgInfo(Remark = "跟踪止盈的最小盈利率,大于这个盈利率才会止盈",DefaultVal ="0.005")]
        public decimal profitRate { get; set; }=0.005m;
        protected override bool IsCheckTrend => false;
        public TuPo_2()
        {
            //var list = new List<ArgInfo>();

            //var a1 = new ArgInfo() { Name = "accountMaxLossRatio", Remark = "仓位最大可承受亏损", DefaultVal = "0.02" };
            //var a2 = new ArgInfo() { Name = "stopLossRatio", Remark = "止损计算亏损率", DefaultVal = "0.005" };
            //var a3 = new ArgInfo() { Name = "ProfitRate1", Remark = "第一止盈点止盈率", DefaultVal = "0.015" };
            //var a4 = new ArgInfo() { Name = "NowPeriod", Remark = "周期", DefaultVal = "60" };
            //list.AddRange(new[] { a1, a2, a3,a4 });
            //ArgInfos = list.ToArray();
        }


        public override void Init()
        {
            base.Init();
            Log.Debug("策略参数值", new { accountMaxLossRatio, stopLossRatio, ProfitRate1 });
        }

        public override void Execute(TradeCmd cmdVal)
        {

            //var ret = Exchange.GetRecordsAsync(cmdVal.Period);
            var account = Exchange.GetAccountAsync();
            var tck = Exchange.GetTickerAsync();

            //交易：仓位计算
            var nowPrice = tck.Result.Buy;
            //计算止损：数量，止损价，止损类型(固定）
            decimal stopLoss = StopLossCalc(nowPrice, cmdVal.IsLong.Value);
            decimal buyAmount = AmountCalc(account.Result, stopLoss, nowPrice, cmdVal.IsLong.Value);

            var id = cmdVal.IsLong.Value ? Exchange.BuyAsync(buyAmount) : Exchange.SellAsync(-1, buyAmount);  // execTrade(DirectionTo.InFor(cmdVal.IsLong), buyAmount);
            //计算止盈：数量，止盈价，止盈类型(跟踪、固定)，止盈后动作(设置止损)
            var spl = new StopLoss(this, new StopLoss.StopLossInfo() {SourceOrderId=""+id.Result, Sid = GetHashCode() + "", Amount = buyAmount, StopLossPrice = stopLoss, IsCloseBuy = cmdVal.IsLong.Value});
            
            var profitPrice = StopProfitCalc(nowPrice, cmdVal.IsLong.Value);
            var fp = new TrailingStep2.FixedProfit(this) { Amount = buyAmount - Exchange.getAmount(buyAmount / 2), Price = profitPrice, IsLong = cmdVal.IsLong.Value };
            fp.AfterFun = () => spl.Data.StopLossPrice = nowPrice;
            fp.SourceOrderId = id.Result+"";
            var tp = new TrailingProfit(this, new TrailingProfit.TrailingProfitData() { SourceOrderId = id.Result, Amount = Exchange.getAmount(buyAmount / 2), InPrice = nowPrice, CloseDirection = DirectionTo.CloseFor(cmdVal.IsLong) },profitSlideRate,profitRate);
            tp.SetProfitRate(profitPrice);
            new TuPo2TaskItem(this) { stopLoss1 = spl, fixedProfit = fp, trailingProfit = tp, sourcePrice = nowPrice, Exchange = Exchange }.Init();
            //监控添加
            return;
        }
        public class TuPo2TaskItem
        {
            internal StopLoss stopLoss1;
            internal TrailingStep2.FixedProfit fixedProfit;
            internal TrailingProfit trailingProfit;
            int step = 1;
            internal decimal sourcePrice = 0;
            internal IExchange Exchange;

            public StrategyBase2 StrategyBase2 { get; }

            public TuPo2TaskItem(StrategyBase2 strategyBase2)
            {
                StrategyBase2 = strategyBase2;
            }

   

            public void Init()
            {
                Exchange.TickerChangeEvent += Exchange_TickerChangeEvent;
            }
            private void Exchange_TickerChangeEvent(object sender, Ticker e)
            {
                if (StrategyBase2.IsEnd)
                {
                    Exit();
                    return;
                }
                Execute(e);
            }

            public void Execute(Ticker tck)
            {
                
                var p = tck;
                var re = stopLoss1.Execute(p);
                if (re)
                {
                    Exit();
                }
                else if (step == 1)
                {

                    var re1 = fixedProfit.Execute(p);
                    if (re1)
                    {
                        step = 2;
                        stopLoss1.Data.StopLossPrice = sourcePrice;
                        stopLoss1.Data.Amount = stopLoss1.Data.Amount - fixedProfit.Amount;
                    }
                    return;
                }
                else
                {
                    var re2 = trailingProfit.Execute(p);
                    if (re2)
                    {
                        Exit();
                    }
                    return;
                }
            }
            public void Exit()
            {
                Exchange.TickerChangeEvent -= Exchange_TickerChangeEvent;
            }

        }

        private decimal AmountCalc(Account account, decimal stopLoss, decimal nowPrice, bool isLong)
        {
            var longVal = isLong ? 1 : -1;
            var am = longVal * account.Balance * accountMaxLossRatio / (nowPrice - stopLoss);
            return Exchange.getAmount(am);
        }
        /// （当前价格/购入价格)>0.015时平一半，剩余追踪
        decimal StopProfitCalc(decimal price, bool isLong)
        {
            return ISysFun.CalcPriceByProfitRate(ProfitRate1, price, isLong);
        }
        /// 购入价格*（1-0.5%）
        private decimal StopLossCalc(decimal price, bool isLong)
        {
            var stopLoss = isLong ? price * (1 - stopLossRatio) : price * (1 + stopLossRatio);
            Log.Debug(this.GetType().Name + "止损计算信息", new { stopLoss });
            return stopLoss;
        }


        public class TradeCmd : TradeInfo
        {
            //public decimal? Price { get; set; }
            //public decimal[] sells { get; set; }

        }
    }
}
